import { getMaterial, handlePostException, savePostData } from "../../api/webApi/index.js"
import { arrayToValueOfConfig, closeUnwantedPages } from "../../utils/index.js"
import { createNamedStore } from "../../config/index.js"
// 创建本地缓存存储实例
export const postingIntervalStore = createNamedStore("posting-intervals")

/**
 * 检查是否应该执行发帖任务
 * @param {string} accountId - 账号ID
 * @param {number} intervalPosting - 配置的发帖间隔（小时）
 * @returns {Promise<Object>} - 检查结果，包含shouldSkip（true表示跳过发帖）和message属性
 */
export async function shouldSkipPosting(accountId, intervalPosting) {
  const cacheKey = `threads_last_post_${accountId}`
  const cacheStatusKey = `threads_post_status_${accountId}` // 新增状态键，用于存储上次发帖成功/失败状态
  const lastPostTime = postingIntervalStore.get(cacheKey)
  const lastPostStatus = postingIntervalStore.get(cacheStatusKey)
  const currentTime = Date.now()

  // 结果对象
  const result = {
    shouldSkip: false,
    message: "",
    lastPostTime: lastPostTime,
    currentTime: currentTime,
  }

  if (lastPostTime) {
    // 检查上次发帖状态，如果失败则使用1小时间隔，否则使用配置的间隔
    const actualInterval = lastPostStatus === "failed" ? 1 : intervalPosting
    const hoursSinceLastPost = (currentTime - lastPostTime) / (1000 * 60 * 60)

    console.log(`上次发帖时间：${new Date(lastPostTime).toLocaleString()}, 状态: ${lastPostStatus || "成功"}, 已经过去${hoursSinceLastPost.toFixed(2)}小时`)
    console.log(`当前间隔设置：${lastPostStatus === "failed" ? "1小时(失败重试)" : `${actualInterval}小时(正常间隔)`}`)

    if (hoursSinceLastPost < actualInterval) {
      result.shouldSkip = true
      result.message = `未达到发帖间隔时间，还需等待${(actualInterval - hoursSinceLastPost).toFixed(2)}小时`
      return result
    }
  }

  // 不需要跳过，可以继续发帖
  return result
}

export async function td_posting_main(task, browser, index, taskId, publishPostParams) {
  const composedTask = task.composedTask
  console.log("task====>td_posting_main", task)
  console.log("task====>td_posting_main.platformAccount", task.platformAccount)
  // 获取运行配置
  const config = composedTask.config || []
  // 读取配置参数
  // 发帖间隔时间的最大最小偏移值
  const minCount = arrayToValueOfConfig(config, "min_count")
  const maxCount = arrayToValueOfConfig(config, "max_count")
  // 发帖的间隔时间（小时）
  const intervalPosting = arrayToValueOfConfig(config, "interval_posting") * getRandomArbitrary(Number(minCount), Number(maxCount))
  console.log(`当前任务时间间隔${intervalPosting}小时`)

  if (!intervalPosting) {
    console.log("任务需要设置发帖时间间隔--------")
    return
  }

  // 检查是否满足发帖间隔条件
  const accountId = task.platformAccount
  const cacheKey = `threads_last_post_${accountId}`
  const cacheStatusKey = `threads_post_status_${accountId}`

  // 使用新的检查函数
  const checkResult = await shouldSkipPosting(accountId, intervalPosting)
  if (checkResult.shouldSkip) {
    console.log(checkResult.message)
    return {
      success: false,
      message: checkResult.message,
      taskId,
    }
  }

  // 更新最后发帖时间为当前时间
  const currentTime = checkResult.currentTime
  postingIntervalStore.set(cacheKey, currentTime)
  // 初始化设置为成功状态
  postingIntervalStore.set(cacheStatusKey, "success")

  //  发帖任务
  console.log("开始执行Threads发帖任务")
  // 解构task获取必要参数，兼容新旧两种格式
  let mediaUrls = []
  let content = ""
  // 获取主播id获取素材
  const mediaUrlRes = await getMaterial(
    {
      platformAccount: task.platformAccount,
      hostId: task.host.id,
    },
    {
      headers: {
        "X-Platform": task.platformName,
        "X-ScriptApp": "browser",
        "X-Device-Id": task.deviceId,
        "tenant-id": task.tenantId,
      },
    }
  )
  console.log("素材获取结果:", mediaUrlRes.data)
  content = mediaUrlRes.data?.content || ""
  const getInfo = mediaUrlRes.data?.list || []
  if (getInfo && getInfo.length > 0) {
    mediaUrls = getInfo.map((item) => item.url)
  }
  const {
    threadsDomain = "https://www.threads.net", // Threads网站域名
  } = task || {}

  if (!content) {
    console.error("无效的帖子内容")
    // 设置失败状态，下次1小时后重试
    postingIntervalStore.set(cacheStatusKey, "failed")
    return { success: false, message: "无效的帖子内容", taskId }
  }

  // 创建结果对象
  const result = {
    success: false,
    message: "",
    postLink: "",
    taskId,
  }

  // 获取页面实例
  let page
  try {
    await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 10))
    await closeUnwantedPages(browser, ["www.threads.net", "start.adspower.net"])
    // 创建新页面
    page = await browser.newPage()
    // 设置页面视口
    await page.setViewport({ width: 1920, height: 1080 })
    // 访问Threads首页
    console.log("正在访问Threads首页...")
    await page.goto(threadsDomain, { waitUntil: "networkidle2", timeout: 60000 })

    // 等待页面加载完成
    await new Promise((resolve) => setTimeout(resolve, 3000))

    // 查找并点击发布按钮
    console.log("寻找发布按钮...")
    const publishButton = await findPublishButton(page)
    if (!publishButton) {
      throw new Error("未找到发布按钮")
    }

    const rect = await publishButton.boundingBox()
    await page.mouse.move(rect.x + rect.width / 2, rect.y + rect.height / 2)
    await page.mouse.down()
    await new Promise((resolve) => setTimeout(resolve, 100))
    await page.mouse.up()

    console.log("点击完成，检查是否成功发布")
    await new Promise((resolve) => setTimeout(resolve, 2000))

    // 填写发帖文案
    console.log("填写发帖文案")
    await fillPostContent(page, content)

    // 上传媒体文件
    console.log("准备上传媒体文件")
    console.log("task.platformAccount===mediaUrls", task.platformAccount, mediaUrls)
    await uploadMedia(page, browser, mediaUrls)

    // 点击发布
    console.log("发布帖子")
    await submitPost(page)

    // 等待发布完成
    console.log("等待发布完成，点击个人中心验证发布状态")

    // 等待页面稳定
    await new Promise((resolve) => setTimeout(resolve, 3000))

    // 获取个人中心tab栏
    const profileButtonSelector = ".x1n2onr6:nth-child(5) .xefz13k"
    try {
      await page.waitForSelector(profileButtonSelector, { timeout: 10000 })
      const profileButton = await page.$(profileButtonSelector)
      console.log("找到个人中心按钮，准备点击")

      if (profileButton) {
        // 点击个人中心
        await profileButton.click()
        console.log("已点击个人中心按钮")

        // 验证帖子是否发布成功
        const isPublished = await verifyPostPublished(page, content, 60000)

        if (isPublished.success) {
          // 发布成功，更新本地缓存中的最后发帖时间和状态
          postingIntervalStore.set(cacheKey, currentTime)
          postingIntervalStore.set(cacheStatusKey, "success")
          console.log(`发帖成功，已更新本地缓存的发帖时间: ${new Date(currentTime).toLocaleString()}`)

          // 生成下次发帖的推荐时间
          const nextPostingTime = new Date(currentTime + intervalPosting * 60 * 60 * 1000)
          console.log(`下次建议发帖时间: ${nextPostingTime.toLocaleString()}`)

          // 更新结果
          result.success = true
          result.message = "帖子发布成功并已验证"
          result.postLink = isPublished.postLink
          console.log("任务完成，帖子发布成功:", isPublished.postLink)
          // 保存帖子到后台
          // 调保存接口
          const params = {
            platformAccount: task.platformAccount?.trim(),
            author: task.platformAccountNickName?.trim(),
            title: "",
            content: content?.trim(),
            viewNum: 0,
            likeNum: 0,
            commentNum: 0,
            mediaUrls: getInfo?.map((item) => item.url) || [],
            postDate: new Date().toISOString().split("T")[0] || "",
          }
          console.log("发送帖子的参数", params)
          const saveRes = await savePostData(params, {
            headers: {
              "X-Platform": task.platformName,
              "X-ScriptApp": "browser",
              "X-Device-Id": task.deviceId,
              "tenant-id": task.tenantId,
            },
          })
          console.log("saveRes===>", saveRes)
        } else {
          // 设置失败状态，下次1小时后重试
          postingIntervalStore.set(cacheStatusKey, "failed")
          throw new Error(isPublished.message || "无法在个人中心找到刚发布的帖子")
        }
      } else {
        // 设置失败状态，下次1小时后重试
        postingIntervalStore.set(cacheStatusKey, "failed")
        throw new Error("找到个人中心选择器但无法获取元素")
      }
    } catch (profileError) {
      // 设置失败状态，下次1小时后重试
      postingIntervalStore.set(cacheStatusKey, "failed")
      console.error("访问个人中心出错:", profileError.message)
      throw new Error("验证发布失败: " + profileError.message)
    }
  } catch (error) {
    // 设置失败状态，下次1小时后重试
    postingIntervalStore.set(cacheStatusKey, "failed")
    console.error("发帖任务执行失败:", error.message)
    result.success = false
    result.message = `发帖失败: ${error.message}`
    // 处理发帖异常
    const params = {
      hostAssetId: getInfo ? getInfo[0]?.folderId : "",
      hostAssetRecordId: getInfo ? getInfo[0]?.hostAssetRecordId : "",
      accountId: task.platformAccount,
      operatorName: task.host.name,
      errorMessage: "测试回滚",
      deviceId: task.deviceId,
    }
    const handlePostExceptionRes = await handlePostException(params, {
      headers: {
        "X-Platform": task.platformName,
        "X-Device-Id": task.deviceId,
        "X-ScriptApp": "browser",
        "tenant-id": task.tenantId,
        "Content-Type": "application/x-www-form-urlencoded",
      },
    })
    console.log("处理发帖异常结果:", handlePostExceptionRes)
  } finally {
    // 关闭页面
    if (page && !page.isClosed()) {
      await page.close()
    }
  }

  return result
}

/**
 * 查找发布按钮
 * @param {Page} page - Puppeteer页面实例
 * @returns {Promise<ElementHandle|null>} 发布按钮元素
 */
async function findPublishButton(page) {
  try {
    // 等待元素出现
    // 尝试多种可能的发布按钮选择器
    const selectors = ['div[class="xc26acl x6s0dn4 x78zum5 xl56j7k x6ikm8r x10wlt62 x1swvt13 x1pi30zi xlyipyv xp07o12"]']
    await page.waitForSelector(selectors[0], { timeout: 10000 })

    for (const selector of selectors) {
      const button = await page.$(selector)
      if (button) {
        return button
      }
    }

    return null
  } catch (error) {
    console.error("查找发布按钮时出错:", error)
    return null
  }
}

/**
 * 填写发帖文案
 * @param {Page} page - Puppeteer页面实例
 * @param {string} content - 帖子内容
 */
async function fillPostContent(page, content) {
  try {
    // 等待文本输入区域出现
    await page.waitForSelector('div[contenteditable="true"]', { timeout: 10000 })

    // 尝试定位文本输入框
    const textArea = await page.$('div[contenteditable="true"]')

    if (textArea) {
      // 清空现有内容
      await textArea.click({ clickCount: 3 }) // 全选
      await page.keyboard.press("Backspace") // 删除

      // 输入新内容
      await textArea.type(content, { delay: 50 })
    } else {
      throw new Error("未找到文本输入区域")
    }
  } catch (error) {
    console.error("填写发帖文案时出错:", error)
    throw new Error("填写文案失败: " + error.message)
  }
}

/**
 * 上传媒体文件
 * @param {Page} page - Puppeteer页面实例
 * @param {Browser} browser - Puppeteer浏览器实例
 * @param {string[]} mediaUrls - 媒体URL列表
 */
async function uploadMedia(page, browser, mediaUrls) {
  try {
    // 导入axios
    const axios = await import("axios")
    const fs = await import("fs")
    const path = await import("path")
    const os = await import("os")

    // 查找上传按钮
    const uploadButton = (await page.$('input[type="file"]')) || (await page.$('[aria-label*="Upload"]')) || (await page.$('[aria-label*="Attach"]'))

    if (!uploadButton) {
      // 如果找不到上传按钮，尝试点击可能的触发按钮
      const triggerButton = (await page.$('button[aria-label*="Add media"]')) || (await page.$('button[aria-label*="Upload"]'))

      if (triggerButton) {
        await triggerButton.click()
        await new Promise((resolve) => setTimeout(resolve, 2000))

        // 再次查找上传按钮
        const uploadInput = await page.$('input[type="file"]')
        if (!uploadInput) {
          throw new Error("找不到上传文件的输入框")
        }
      } else {
        throw new Error("找不到上传媒体的按钮")
      }
    }
    console.log("mediaUrls====>", mediaUrls)
    // 处理每个媒体文件
    for (const mediaUrl of mediaUrls) {
      // 下载媒体文件
      console.log(`正在使用axios下载媒体文件: ${mediaUrl}`)

      // 创建临时文件路径
      const isVideo = mediaUrl.toLowerCase().endsWith(".mp4") || mediaUrl.toLowerCase().endsWith(".mov") || mediaUrl.toLowerCase().includes("video")
      const fileName = isVideo ? "temp_video.mp4" : "temp_image.jpg"
      const tempFilePath = path.join(os.tmpdir(), fileName)

      try {
        // 使用axios下载文件
        const response = await axios.default.get(mediaUrl, {
          responseType: "arraybuffer",
          headers: {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36",
            Referer: "https://www.threads.net",
          },
          timeout: 60 * 1000, // 60秒超时
        })

        // 将文件保存到临时目录
        fs.writeFileSync(tempFilePath, Buffer.from(response.data))
        console.log(`媒体文件已下载到: ${tempFilePath}`)

        // 将媒体文件上传到Threads
        const uploadInput = await page.$('input[type="file"]')

        if (uploadInput) {
          // 准备上传文件
          await uploadInput.uploadFile(tempFilePath)

          // 等待上传完成
          await new Promise((resolve) => setTimeout(resolve, 5000))

          // 检查是否上传成功
          const uploadError = (await page.$('[aria-label*="Error"]')) || (await page.$("text/Upload failed/i"))
          if (uploadError) {
            throw new Error("媒体上传失败")
          }

          // 上传成功后删除临时文件
          try {
            fs.unlinkSync(tempFilePath)
            console.log(`临时文件已删除: ${tempFilePath}`)
          } catch (unlinkError) {
            console.error(`删除临时文件失败: ${unlinkError.message}`)
          }
        } else {
          throw new Error("未找到文件上传输入框")
        }
      } catch (downloadError) {
        console.error(`下载媒体文件失败: ${downloadError.message}`)
        throw new Error(`下载媒体文件失败: ${mediaUrl}，错误: ${downloadError.message}`)
      }
    }

    // 等待所有媒体上传完成
    await new Promise((resolve) => setTimeout(resolve, 3000))
  } catch (error) {
    console.error("上传媒体文件时出错:", error)
    throw new Error("上传媒体失败: " + error.message)
  }
}
/**
 * 提交发布帖子
 * @param {Page} page - Puppeteer页面实例
 */
async function submitPost(page) {
  try {
    // 外层容器选择器
    const outerSelector = "div.x15zctf7"

    // 目标按钮的父级选择器
    const innerSelector = ".x2lah0s:nth-child(1) > .x1g2r6go"

    // 查找外层容器
    const outerElement = await page.$(outerSelector)
    if (!outerElement) {
      throw new Error("未找到外层发布按钮容器")
    }

    // 在外层容器中查找目标按钮
    const publishBtn = await outerElement.$(innerSelector)
    if (!publishBtn) {
      throw new Error("未找到发布提交按钮")
    }
    const rect = await publishBtn.boundingBox()
    await page.mouse.move(rect.x + rect.width / 2, rect.y + rect.height / 2)
    await page.mouse.down()
    await new Promise((resolve) => setTimeout(resolve, 100))
    await page.mouse.up()
  } catch (error) {
    console.error("提交发布帖子时出错:", error)
    throw new Error("提交发布失败: " + error.message)
  }
}

/**
 * 验证帖子是否发布成功
 * @param {Page} page - Puppeteer页面实例
 * @param {string} expectedContent - 预期的帖子内容
 * @param {number} timeout - 超时时间（毫秒）
 * @returns {Promise<Object>} 验证结果
 */
async function verifyPostPublished(page, expectedContent, timeout = 60000) {
  console.log(`开始验证帖子发布状态，文案内容：${expectedContent.substring(0, 30)}...，超时时间：${timeout / 1000}秒`)

  // 创建验证结果对象
  const result = {
    success: false,
    message: "",
    postLink: "",
  }

  const startTime = Date.now()

  try {
    // 等待个人资料页面加载
    try {
      await page.waitForSelector('div[class="x1amjocr x78zum5 xz9dl7a xsag5q8 xj1t3w4 x21njyp x1xukajm x155y65f"]', { timeout: 15000 })
      console.log("个人中心页面加载完成")
    } catch (waitError) {
      console.log("等待个人中心帖子列表超时，继续尝试查找")
    }

    // 循环检查，直到找到匹配的帖子或超时
    while (Date.now() - startTime < timeout) {
      try {
        await new Promise((resolve) => setTimeout(resolve, 3000))
        const postList = await page.$$(".x1e4zzel > .x78zum5 > div")
        const visiblePosts = []

        for (const post of postList) {
          const box = await post.boundingBox()
          if (box) {
            visiblePosts.push(post)
          }
        }
        console.log(`找到${visiblePosts.length}条帖子，开始匹配内容`)
        for (let index = 0; index < visiblePosts.length; index++) {
          const visiblePost = visiblePosts[index]
          const selectors = [
            'div[class="x1a6qonq x6ikm8r x10wlt62 xj0a0fe x126k92a x6prxxf x7r5mf7"]', // 文案
          ]
          const captionElement = await visiblePost.$(selectors[0])
          if (!captionElement) {
            console.log("  [文案] 未找到，跳过该帖子")
            continue
          }
          let captionText = await page.evaluate((el) => el.textContent.trim()?.replace(/翻译|翻譯|translation|translate|翻訳|terjemahan/g, ""), captionElement)
          console.log(`  [文案] 找到：${captionText}`)
          // 比较文案是否匹配
          if (captionText?.trim() === expectedContent?.trim()) {
            console.log("帖子发布成功，文案内容：", captionText)

            // 尝试获取帖子链接
            try {
              const linkElement = await visiblePost.$('a[href*="/post/"]')
              if (linkElement) {
                const href = await page.evaluate((el) => el.href, linkElement)
                result.postLink = href
              } else {
                result.postLink = page.url()
              }
            } catch (linkError) {
              console.log("获取帖子链接失败:", linkError.message)
              result.postLink = page.url()
            }

            // 设置成功结果并返回
            result.success = true
            result.message = `帖子发布成功: ${captionText.substring(0, 30)}${captionText.length > 30 ? "..." : ""}`
            return result
          }
        }

        console.log("未找到匹配帖子，等待后重试...")
        await new Promise((resolve) => setTimeout(resolve, 5000))
      } catch (checkError) {
        console.log("检查帖子时出错:", checkError.message)
        await new Promise((resolve) => setTimeout(resolve, 3000))
      }
    }

    // 超时未找到
    result.success = false
    result.message = `验证超时：${timeout / 1000}秒内未找到匹配内容的帖子`
    return result
  } catch (error) {
    console.error("验证帖子发布状态时出错:", error)
    result.success = false
    result.message = `验证失败: ${error.message}`
    return result
  }
}

/**
 * 等待发布完成
 * @param {Page} page - Puppeteer页面实例
 */
async function waitForPublishComplete(page) {
  const timeoutMs = 30000 // 30 秒超时

  try {
    await Promise.race([
      new Promise((_, reject) => setTimeout(() => reject(new Error("发布过程等待超时")), timeoutMs)),
      page.waitForNavigation({ timeout: timeoutMs }).catch(() => {}),
      page.waitForSelector('div[class="xm4wzdf xwhw2v2"]', { timeout: timeoutMs }).catch(() => {}),
    ])

    // 额外等待确保页面完全加载
    await new Promise((resolve) => setTimeout(resolve, 3000))
  } catch (error) {
    console.error("等待发布完成时出错:", error)
    // 这里不抛出错误，因为我们将在后面通过个人中心验证发布状态
    console.log("发布状态不明确，将通过个人中心验证")
  }
}

//取随机值
export function getRandomArbitrary(min, max) {
  return Math.random() * (max - min) + min
}
